package web.stu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import web.stu.common.ErrorCode;
import web.stu.exception.BusinessException;
import web.stu.mapper.CourseMapper;
import web.stu.model.dto.CourseDTO;
import web.stu.model.dto.course.QueryCourseDTO;
import web.stu.model.entity.Course;
import web.stu.model.entity.Score;
import web.stu.model.entity.User;
import web.stu.model.enums.UserRoleEnum;
import web.stu.model.vo.CourseVO;
import web.stu.service.CourseService;
import web.stu.service.ScoreService;
import web.stu.service.UserService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author administer
 * @description 针对表【course(课程表)】的数据库操作Service实现
 * @createDate 2025-05-13 19:55:14
 */
@Service
@Slf4j
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Resource
    private ScoreService scoreService;

    @Resource
    private UserService userService;

    @Resource
    private CourseMapper courseMapper;

    @Override
    public Page<CourseVO> pageCourses(QueryCourseDTO queryCourseDTO, HttpServletRequest request) {
        // 非空判断
        if (queryCourseDTO == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 提取分页信息
        long current = queryCourseDTO.getCurrent();
        long pageSize = queryCourseDTO.getPageSize();
        Page<Course> coursePage = new Page<>(current, pageSize);

        // 判断身份，若为学生则只能设置学生ids为当前用户
        User loginUser = userService.getLoginUser(request);
        boolean isStudent = userService.isCompareRole(loginUser, UserRoleEnum.STUDENT.getKey());
        if (isStudent) {
            queryCourseDTO.setStudentIds(Collections.singletonList(userService.getLoginUser(request).getId()));
        }

        // 根据ids 查询关联表的id信息
        List<Integer> courseIds = Collections.emptyList();
        if (CollectionUtil.isNotEmpty(queryCourseDTO.getStudentIds())) {
            List<Integer> studentIds = queryCourseDTO.getStudentIds();
            courseIds = courseMapper.getCourseIdsByStudentId(studentIds);
        }

        List<Integer> resultIds = Collections.emptyList();
        if (isStudent) {
            // 两种情况 1、role 为学生 这个时候不能返回所有值
            resultIds = courseIds;
        } else {
            // 2、role 不为学生，这个时候需要返回所有值
            // 这里将查询ids 条件与查询出来的ids 求交集 作为查询queryWrapper条件
            resultIds = new ArrayList<>(CollUtil.intersection(courseIds, queryCourseDTO.getStudentIds()));
        }
        // 条件查询
        queryCourseDTO.setIds(resultIds);
        QueryWrapper<Course> queryWrapper = getQueryWrapper(queryCourseDTO, request);

        // 根据学生分页查询关联表课程信息
        Page<Course> page = this.page(coursePage, queryWrapper);
        Page<CourseVO> courseVOPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<Course> courseList = page.getRecords();
        List<CourseVO> courseVOList = courseList.stream().map(course -> {
            CourseVO courseVO = BeanUtil.copyProperties(course, CourseVO.class);
            //如果为学生需要处理
            if (isStudent) {
                String teacherName = courseMapper.getTeacherByStudentCourse(loginUser.getId(), course.getId());
                courseVO.setTeacherName(teacherName);
            }
            return courseVO;
        }).collect(Collectors.toList());
        courseVOPage.setRecords(courseVOList);
        return courseVOPage;
    }

//    @Override
//    public Page<CourseVO> pageCourses(Integer pageNum, Integer pageSize) {
//        Page<Course> page = new Page<>(pageNum, pageSize);
//        this.page(page);
//
//        Page<Course> voPage = new Page<>();
//        voPage.setTotal(page.getTotal());
//        voPage.setRecords(page.getRecords());
//
//        return voPage;
//    }

    @Override
    public void addCourse(CourseDTO courseDTO) {
        // 检查课程名称是否已存在
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getCourseName, courseDTO.getCourseName());
        if (this.count(wrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该课程已存在");
        }

        // 赋值
        Course course = new Course();
        BeanUtil.copyProperties(courseDTO, course);
        // 进行添加
        boolean result = this.save(course);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加课程失败");
        }
    }

    @Override
    public void updateCourse(CourseDTO courseDTO, HttpServletRequest request) {
        // 查询权限 不是管理无权操作
        User loginUser = userService.getLoginUser(request);
        if (!userService.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "不为管理员，不能修改课程");
        }
        // 检查课程是否存在
        Course existingCourse = this.getById(courseDTO.getId());
        if (existingCourse == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "课程不存在");
        }

        // 检查课程名称是否与其他课程冲突
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getCourseName, courseDTO.getCourseName())
                .ne(Course::getId, courseDTO.getId());
        if (this.count(wrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "课程名称已存在");
        }
        // 赋值
        Course course = new Course();
        BeanUtil.copyProperties(courseDTO, course);
        // 进行修改
        boolean result = this.updateById(course);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新课程失败");
        }
    }

    @Override
    public void deleteCourseById(Integer id, HttpServletRequest request) {
        // 查询权限 不是管理无权操作
        User loginUser = userService.getLoginUser(request);
        if (!userService.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "不为管理员，不能删除课程");
        }

        // 检查课程是否存在
        Course course = this.getById(id);
        if (course == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "课程不存在");
        }

        // 检查是否有成绩关联该课程 score student_course teacher_course
        LambdaQueryWrapper<Score> scoreWrapper = new LambdaQueryWrapper<>();
        scoreWrapper.eq(Score::getCourseId, id);
        if (scoreService.count(scoreWrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该课程已有成绩记录，无法删除");
        }
        if (courseMapper.countCourseStudentCourse(id) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该课程已有学生选课记录，无法删除");
        }
        if (courseMapper.countCourseTeacherCourse(id) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该课程已有教师授课记录，无法删除");
        }


        boolean result = this.removeById(id);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除课程失败");
        }
    }

    @Override
    public CourseVO getCourseById(Integer id, HttpServletRequest request) {
        Course course = this.getById(id);
        if (course == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "课程不存在");
        }
        CourseVO courseVO = new CourseVO();
        BeanUtil.copyProperties(course, courseVO);
        User loginUser = userService.getLoginUser(request);
        boolean isStudent = userService.isCompareRole(loginUser, UserRoleEnum.STUDENT.getKey());
        if (isStudent) {
            String teacherName = courseMapper.getTeacherByStudentCourse(loginUser.getId(), id);
            courseVO.setTeacherName(teacherName);
        }
        return courseVO;
    }

    @Override
    public List<CourseVO> listCourseByStudentIdAndTeacherIdAndClassId(Integer studentId, Integer teacherId, Integer classId, HttpServletRequest request) {
        // 非空判断
        if (studentId == null || teacherId == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 获取该教师 教授并且该课程学生选择的课程
        List<Course> courseList = Collections.emptyList();
        List<Integer> courseIds = courseMapper.listCourseIdsByStudentId(studentId, teacherId, classId);
        if (courseIds != null && !courseIds.isEmpty()) {
            courseList = this.listByIds(courseIds);
        }

        //如果为学生需要处理
        User loginUser = userService.getLoginUser(request);
        boolean isStudent = userService.isCompareRole(loginUser, UserRoleEnum.STUDENT.getKey());
        List<CourseVO> courseVOList = courseList.stream().map(course -> {
            CourseVO courseVO = BeanUtil.copyProperties(course, CourseVO.class);
            //如果为学生需要处理
            if (isStudent) {
                String teacherName = courseMapper.getTeacherByStudentCourse(loginUser.getId(), course.getId());
                courseVO.setTeacherName(teacherName);
            }
            return courseVO;
        }).collect(Collectors.toList());
        return courseVOList;
    }


    private QueryWrapper<Course> getQueryWrapper(QueryCourseDTO queryCourseDTO, HttpServletRequest request) {
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        // 非空判断
        if (queryCourseDTO == null) {
            return wrapper;
        }
        // 提取参数
        List<Integer> ids = queryCourseDTO.getIds();
        String courseName = queryCourseDTO.getCourseName();
        BigDecimal credit = queryCourseDTO.getCredit();
        Integer hours = queryCourseDTO.getHours();
        String description = queryCourseDTO.getDescription();


        wrapper.in(CollectionUtil.isNotEmpty(ids), "id", ids);
        wrapper.like(StrUtil.isNotBlank(courseName), "course_name", courseName);
        wrapper.eq(ObjUtil.isNotEmpty(credit), "credit", credit);
        wrapper.eq(hours != null, "hours", hours);
        wrapper.like(StrUtil.isNotBlank(description), "description", description);

        return wrapper;
    }


}




